/*
    This file is part of Advanced Strategic Command; http://www.asc-hq.de
    Copyright (C) 1994-1999  Martin Bickel  and  Marc Schellenberger

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING. If not, write to the
    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    Boston, MA  02111-1307  USA
*/

#if HAVE_CONFIG_H
#  include <config.h>
#endif

#include <cstring>

#include <SDL_types.h>
#include <SDL_endian.h>

#include "../basestrm.h"
#include "../strtmesg.h"
#include "../ascstring.h"
#include "../errors.h"

#ifdef logging
 void addToLog ( const ASCString& str )
 {
   FILE* f = fopen ( "demount.log", "at");
   fprintf(f, str.c_str() );
   fprintf(f, "\n" );
   fclose(f);
 }
#else
  #define addToLog(a)
#endif

void fatalError ( const ASCString& s )
{
   fprintf( stderr, "%s \n", s.c_str() );
   exit(1);
}

void displayLogMessage( int verbosity, const ASCString& message )
{}


int readInt  ( FILE* f )
{
   int i;
   fread( &i, 1, 4, f );
   return SDL_SwapLE32(i);
}


// including the command line parser, which is generated by genparse
#include "../clparser/demount.cpp"

int main(int argc, char *argv[] )
{
   addToLog( "Demount started\n");
   
   Cmdline cl ( argc, argv );

   if ( cl.v() ) {
      cout << argv[0] << " " << getVersionString() << endl;
      exit(0);
   }

   if ( argc == cl.next_param() ) {
      cl.usage();
      exit(1);
   }


   Uint32 pos;
   Uint32 num = 0;
   for ( int a = cl.next_param(); a < argc; a++ ) {

      addToLog( ASCString("Processing ") + argv[a] );

      FILE* fp = fopen ( argv[a], filereadmode );
      if ( !fp )
         fatalError ( ASCString("Could not open file ") + argv[a] + " for reading!" );

      /* 64 bit problem ? */
      char magic[4];
      fread(&magic,1,sizeof(magic),fp);

      if (strncmp(magic,"NCBM",4) != 0)
         fatalError("Invalid containerfile: magic not matched");

      addToLog( "Reading pos" );

      /* mikem: somehow I don't like the order */
      pos = readInt( fp );

      addToLog( "Seeking to pos" );

      fseek ( fp, pos, SEEK_SET );

      addToLog( "Reading count" );

      num = readInt( fp );

      addToLog( "Allocating index memory" );

      tcontainerindex* index = new tcontainerindex[num];

      addToLog( "Reading index" );

      Uint32 i;
      for (i = 0; i < num; i++ ) {
         int name = readInt( fp );
         index[i].name = NULL;
         index[i].start = readInt( fp );
         index[i].end = readInt( fp );
         if ( name ) {
            int p = -1;
            index[i].name = new char[1000];
            do {
               fread ( &index[i].name[++p], 1, 1, fp );
            } while ( index[i].name[p] ); /* enddo */
         }
      }

      addToLog( "Closing index" );
      fclose ( fp );

      addToLog( "Opening container pos" );
      opencontainer ( argv[a] );

      Uint32 bufsize = 1000000;

      addToLog( "Reserving buffer" );

      void* buf;
      if ( ! (buf = malloc ( bufsize )) ) {
	printf( "couldn't allocate buffer\n" );
	exit(1);
      }

      addToLog ( ASCString("Number of files: ") + strrr(num));

      for ( i = 0; i < num; i++ ) {
         try {
            addToLog( ASCString("Finding file ") + strrr ( i+1 ));

            tfindfile ff ( index[i].name );
            bool incontainer;
            ASCString nme = ff.getnextname ( NULL, &incontainer );
            if ( incontainer || nme.empty() ) {
               addToLog( "Reserving buffer" );
               tnfilestream instream ( index[i].name, tnstream::reading );
               char namebuf[ maxFileStringSize ];
               int j = 0;
               do {
		 //j++;
                  namebuf[j] = tolower ( index[i].name[j] );
               } while ( namebuf[j++] );

               addToLog( "filename converted" );

               if ( !cl.q() )
                  printf("writing %s \n", namebuf );

               addToLog( "opening output stream" );
               tn_file_buf_stream outstream ( namebuf, tnstream::writing );
               Uint32 size ;
               do { 
		  size = instream.readdata ( buf, bufsize, 0 );
                  outstream.writedata ( buf, size );
               } while ( size == bufsize );
               addToLog( "data written" );
            } else {
               printf("file %s already exists; skipping\n", index[i].name );
               addToLog( ASCString("File ") + index[i].name + " skipped" );
            }
         }
         catch ( tfileerror err ) {
            fatalError( "error writing file " + err.getFileName() );
         } /* endcatch */
         catch ( ... ) {
            fatalError( "Exception caught !" );
         } /* endcatch */

      } /* endfor */

      addToLog( "freeing buffer" );
      free ( buf );
   }
   addToLog( "quitting" );
   return 0;
}
